﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using System.Xml.Serialization;

namespace AmuTools.SFExpress
{
    public class SFXMLHelper
    {
        #region 请求
        public Request<T> CreateRequest<T>(string service, string head, T obj)
        {
            Request<T> request = new Request<T>(service);
            request.Head = head;
            request.Body.Add(obj);
            return request;
        }

        public Request<T> CreateRequest<T>(string service, T obj)
        {
            return CreateRequest<T>(service, service, obj);
        }

        public string ObjToXml<T>(T obj)
        {
            MemoryStream ms = new MemoryStream();
            XmlTextWriter textWriter = new XmlTextWriter(ms, Encoding.GetEncoding("UTF-8"));
            XmlSerializer serializer = new XmlSerializer(typeof(T));
            XmlSerializerNamespaces namespaces = new XmlSerializerNamespaces();
            namespaces.Add(string.Empty, string.Empty);
            serializer.Serialize(textWriter, obj, namespaces);
            string xml = Encoding.UTF8.GetString(ms.GetBuffer());
            return xml;
        }

        public string CreateRequestToXml<T>(string service, string head, T obj)
        {
            Request<T> request = CreateRequest<T>(service, head, obj);
            string xml = ObjToXml<Request<T>>(request);
            return xml;
        }

        public string CreateRequestToXml<T>(string service, T obj)
        {
            return CreateRequestToXml<T>(service, service, obj);
        }
        #endregion

        #region 响应
        public T XmlToObj<T>(string xml)
        {
            XmlSerializer xz = new XmlSerializer(typeof(T));
            byte[] array = Encoding.UTF8.GetBytes(xml);
            MemoryStream stream = new MemoryStream(array);
            return (T)xz.Deserialize(stream);
        }

        public Response<T> CreateResponseFromXml<T>(string service, string head, string xml)
        {
            Response<T> response = XmlToObj<Response<T>>(xml);
            return response;
        }

        public Response<T> CreateResponseFromXml<T>(string service, string xml)
        {
            return CreateResponseFromXml<T>(service, service, xml);
        }
        #endregion
    }

    #region Request、Response
    public class HttpBase<T>
    {
        [XmlAttribute("service")]
        public string Service { get; set; }

        [XmlAttribute("lang")]
        public string Lang { get; set; }

        public string Head { get; set; }

        [XmlArray]
        public List<T> Body = new List<T>();

        public HttpBase()
        {

        }

        public HttpBase(string service, string lang = "zh-CN")
        {
            this.Service = service;
            this.Lang = lang;
        }
    }

    [XmlRoot("Request")]
    public class Request<T>: HttpBase<T>
    {
        public Request(): base() { }
        public Request(string service, string lang = "zh-CN"): base(service, lang) { }
    }
    
    [XmlRoot("Response")]
    public class Response<T> : HttpBase<T>
    {
        [XmlElement("ERROR")]
        public ResponseError Error { get; set; }

        public bool HasError
        {
            get
            {
                if (Head == "ERR") return true;
                else return false;
            }
        }

        public T Result
        {
            get
            {
                if (Body.Count > 0) return Body.First();
                else return default(T);
            }
        }

        public Response() : base() { }
        public Response(string service, string lang = "zh-CN") : base(service, lang) { }
    }

    public class ResponseError
    {
        [XmlAttribute("code")]
        public string Code { get; set; }

        [XmlText]
        public string Text { get; set; }
    }
    #endregion
}
